<?php

/**
 * @title 宝塔服务面板
 * @desc 控制器描述
 * @author 楚羽幽 <admin@hangpu.net>
 */
class BtPanel
{
    # 接口密钥
    private $BT_KEY = "";
    # 面板地址
    private $BT_PANEL = "";

    # 面板是否SSL
    private $BT_SSL = false;

    /**
     * 构造函数
     * @param mixed $BT_PANEL
     * @param mixed $BT_KEY
     * @param mixed $ssl
     * @author 贵州猿创科技有限公司
     * @copyright 贵州猿创科技有限公司
     * @email 416716328@qq.com
     */
    public function __construct(string $BT_PANEL, string $BT_KEY, bool $ssl = false)
    {
        $this->BT_PANEL = $BT_PANEL;
        $this->BT_KEY = $BT_KEY;
        $this->BT_SSL = $ssl;
    }

    /**
     * 获取网络状态
     *
     * @return array
     */
    public function GetNetWork(): array
    {
        return $this->send('/system?action=GetNetWork');
    }

    /**
     * 获取软件列表
     *
     * @param array $data
     * @return array
     */
    public function getSoftList(array $data = []): array
    {
        $data = array_merge([
            'p' => 1,
            'type' => -1,
            'tojs' => 'soft.get_list',
            'force' => 0,
            'query' => ''
        ], $data);
        return $this->send('/plugin?action=get_soft_list', $data);
    }

    /**
     * 获取站点配置
     *
     * @param array $data
     * @return array
     */
    public function getFileBody(array $data = []): array
    {
        $data = array_merge([
            'path' => '',
        ], $data);
        return $this->send('/files?action=GetFileBody', $data);
    }

    /**
     * 保存站点配置
     *
     * @param array $data
     * @return array
     */
    public function SaveFileBody(array $data = []): array
    {
        $data = array_merge([
            'path' => '',
        ], $data);
        return $this->send('/files?action=SaveFileBody', $data);
    }

    /**
     * 保存守护进程
     *
     * @param array $data
     * @return array
     */
    public function saveSupervisor(array $data = []): array
    {
        $data = array_merge([
            'pjname' => '',
            'user' => 'root',
            'path' => '',
            'command' => '',
            'numprocs' => 1,
            'ps' => ''
        ], $data);
        return $this->send('/plugin?action=a&name=supervisor&s=AddProcess', $data);
    }

    /**
     * 启动守护进程
     *
     * @param array $data
     * @return array
     */
    public function startSupervisor(array $data): array
    {
        $data = array_merge([
            'program' => '',
            'numprocs' => 1
        ], $data);
        return $this->send('/plugin?action=a&name=supervisor&s=StartProcess', $data);
    }

    /**
     * 停止守护进程
     *
     * @param array $data
     * @return array
     */
    public function stopSupervisor(array $data): array
    {
        $data = array_merge([
            'program' => '',
            'numprocs' => 1
        ], $data);
        return $this->send('/plugin?action=a&name=supervisor&s=StopProcess', $data);
    }

    /**
     * 获取守护进程列表
     *
     * @param array $data
     * @return array
     */
    public function getSupervisorList(array $data = []): array
    {
        $data = array_merge([
            'action' => 'a',
            'name' => 'supervisor',
            's' => 'GetProcessList',
        ], $data);
        return $this->send('/plugin?action=a&name=supervisor&s=GetProcessList', $data);
    }
    /**
     * 升级composer
     *
     * @param array $data
     * @return array
     */
    public function updateComposer(array $data=[])
    {
        $data = array_merge([
            'action' => 'update_composer',
            'repo'=>'https://mirrors.aliyun.com/composer/'
        ], $data);
        return $this->send('/files?action=update_composer', $data);
    }
    public function getSiteDomains(array $data = []): array
    {
        $data = array_merge([
            'search' => $_SERVER['HTTP_HOST'],
            'table'=>'sites',
            'limit'=>10,
            'p'=>1,
            'type'=>0
        ], $data);
        return $this->send('/data?action=getData', $data);
    }

    /**
     * 发送接口请求
     *
     * @param string $url
     * @param array $data
     * @return array
     */
    private function send(string $url, array $data = []): array
    {
        # 宝塔是否SSL
        $protocol = $this->BT_SSL ? 'https' : 'http';
        # 拼接URL地址
        $api = "{$protocol}://127.0.0.1:{$this->BT_PANEL}{$url}";

        # 取签名
        $p_data = $this->GetKeyData();
        $p_data = array_merge($p_data, $data);

        # 请求面板接口
        $result = $this->HttpPostCookie($api, $p_data);

        # 解析JSON数据
        $response = json_decode($result, true);
        if (isset($response['status']) && !$response['status']) {
            throw new Exception($response['msg']);
        }
        $res = $response ? $response : [];
        return $res;
    }

    /**
     * 构造带有签名的关联数组
     *
     * @return array
     */
    private function GetKeyData(): array
    {
        $now_time = time();
        $p_data = array(
            'request_token' => md5($now_time . '' . md5($this->BT_KEY)),
            'request_time' => $now_time
        );
        return $p_data;
    }

    /**
     * 发起POST请求
     * @param mixed $url 目标网填，带http://
     * @param mixed $data 欲提交的数据
     * @param mixed $timeout
     * @return bool|string
     * @author 贵州猿创科技有限公司
     * @copyright 贵州猿创科技有限公司
     * @email 416716328@qq.com
     */
    private function HttpPostCookie(string $url, $data, int $timeout = 60)
    {
        //定义cookie保存位置
        $cookieFile = ROOT_PATH . '/runtime/bt/' . md5($this->BT_PANEL) . '.cookie';
        $cookieDir = dirname($cookieFile);
        if (!is_dir($cookieDir)) {
            mkdir($cookieDir);
        }
        if (!file_exists($cookieFile)) {
            $fp = fopen($cookieFile, 'w+');
            fclose($fp);
        }

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        curl_setopt($ch, CURLOPT_COOKIEJAR, $cookieFile);
        curl_setopt($ch, CURLOPT_COOKIEFILE, $cookieFile);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        $output = curl_exec($ch);
        curl_close($ch);
        return $output;
    }
}